﻿using System;
using System.Collections.Generic;

namespace DiscoveryLogic.DataServices.DataSources
{
    public class BillPaymentHistory
    {
        #region Private Variables

        private List<BillPayment> _billHistory;
        private string _payeeName;
        private int _payeeId;
        private const double min = 0;
        private const double width = 48;
        private const double height = 32;
        private const int numBars = 5;
        private Double? _averagePayment = null;
        private double[] _paymentAmounts = null;
        private Double? _maxPayment = null;
        private List<BillPayment> _miniBillHistory = null;
               
        #endregion

        #region Public Static Variables

        public static double MAX = 32;
        public static double FLAG_PAYMENT_PERCENT = 0.35;

        #endregion

        #region Public Properties

        public List<BillPayment> BillHistory
        {
            get { return _billHistory; }
            set
            {
                _billHistory = value;

                //set minibillhistory as well
                int numInMini = numBars;
                if (_billHistory.Count < numInMini)
                    numInMini = _billHistory.Count;
                for (int i = 0; i < numInMini; i++)
                {
                    _miniBillHistory = _billHistory.GetRange(_billHistory.Count - numInMini, numInMini);
                }
            }
        }

        public List<BillPayment> MiniBillHistory
        {
            get { return _miniBillHistory; }
        }

        public int PayeeId
        {
            get { return _payeeId; }
            set { _payeeId = value; }
        }

        public string PayeeName
        {
            get { return _payeeName; }
            set { _payeeName = value; }
        }

        public double MaxPayment
        {
            get
            {
                if (_maxPayment.HasValue)
                {
                    return _maxPayment.Value;
                }

                //Calculate the maximum payment the first time this is called
                double currMax = 0;

                // Find Max
                for (int i = 0; i < numBars; i++)
                {
                    if (PaymentAmounts[i] > currMax)
                    {
                        currMax = PaymentAmounts[i];
                    }
                }
                _maxPayment = currMax;
                return _maxPayment.Value;
            }
        }
        
        public double AveragePayment
        {
            get
            {
                if (_averagePayment.HasValue)
                {
                    return _averagePayment.Value;
                }

                //Calculate average payment the first time this is called
                double totalPayment = 0;

                // Find Total payment
                for (int i = 0; i < numBars; i++)
                {
                    totalPayment += PaymentAmounts[i];
                }

                // Find Average
                _averagePayment = totalPayment / numBars;
                return _averagePayment.Value;
            }
        }

        #endregion

        #region Constructors

        public BillPaymentHistory(List<BillPayment> billHist, string payee, int id)
        {
            BillHistory = billHist;
            foreach (BillPayment payment in BillHistory)
            {
                payment.BillPaymentHistory = this;
            }

            this._payeeName = payee;
            this.PayeeId = id;
        }

        #endregion

        #region Private Properties
                
        private double[] PaymentAmounts
        {
            get
            {
                if (_paymentAmounts != null)
                {
                    return _paymentAmounts;
                }

                //Calculate the payment amounts the first time this is called
                //TODO: add locking if multithreading required
                _paymentAmounts = new double[numBars];

                // ASSUMPTION: latest payments are in the back of the list
                for (int i = 0; i < numBars; i++)
                {
                    _paymentAmounts[i] = BillHistory[BillHistory.Count - (numBars - i)].Payment;
                }

                return _paymentAmounts;
            }
        }
                
        #endregion

        #region Public Methods

        public double GetLastPaymentAmount()
        {
            return this.BillHistory[BillHistory.Count - 1].Payment;
        }

        public DateTime GetLastPaymentDate()
        {
            return this.BillHistory[BillHistory.Count - 1].Date;
        }

        #endregion
    }
}